Skip to content

WA-RAILS7-023: Error reporting API migration#758

Merged
kitcommerce merged 3 commits intonextfrom
wa-rails7-023-error-reporting
Mar 5, 2026
Merged

WA-RAILS7-023: Error reporting API migration#758
kitcommerce merged 3 commits intonextfrom
wa-rails7-023-error-reporting

Conversation

@kitcommerce
Copy link

Fixes #754

This evaluates Rails 7.1's Rails.error.report API and adopts it as an additive, opt-in hook for Workarea.

  • Adds Workarea::ErrorReporting.report as a tiny wrapper around Rails.error.report (only called when available).
  • Reports a few handled/swallowed exceptions (network calls + fraud analyzer) so host apps can forward them to their configured provider (Sentry/Bugsnag/etc.).
  • Documents current Workarea behavior + rationale under docs/rails7-migration-patterns/error-reporting.md.

Client impact

Optional. Existing error handling continues to work. Host apps may opt into Rails' error reporter integrations to receive handled/swallowed errors.

@kitcommerce kitcommerce added gate:build-pending Build gate running gate:build-passed Build gate passed review:architecture-pending Review in progress review:simplicity-pending Review in progress review:security-pending Review in progress review:rails-conventions-pending Rails conventions review in progress and removed gate:build-pending Build gate running labels Mar 5, 2026
@kitcommerce
Copy link
Author

Architecture Review

Verdict: PASS

Clean, well-bounded design. Key observations:

  • Provider decoupling ✅ — Workarea::ErrorReporting delegates to Rails' built-in error reporter without coupling to any specific provider (Sentry, Bugsnag, etc.). Host apps register their own subscribers on Rails.error independently. Textbook Dependency Inversion.
  • Backward compatibility ✅ — rails_error_reporter_available? guard makes the entire module a no-op on Rails < 7.1. Existing rescue + logging behavior is completely untouched; the new calls are purely additive.
  • Defensive wrapper ✅ — rescue StandardError => nil ensures error reporting never breaks business logic. Error observability should never cause application failures.
  • Consistent call sites ✅ — All three integrations follow the same pattern: added inside existing rescue blocks with structured context hashes. Clean and predictable.
  • Module boundary ✅ — Stateless module with a single public method. No state, no configuration, no dependencies beyond Rails itself. Minimal surface area.

No architectural concerns. This is a well-executed additive integration.

@kitcommerce
Copy link
Author

🔒 Security Review

Verdict: PASS_WITH_NOTES
Severity: LOW

Summary

No security vulnerabilities introduced. The Workarea::ErrorReporting wrapper is additive, defensive, and follows established patterns for error reporter integration. Minor observations noted below.

Findings

1. Context data forwarded to external reporters — LOW
Context hashes include order_id, class names, and hardcoded service URLs. These flow to whatever error reporter the host app configures (Sentry, Bugsnag, etc.). All values are internal identifiers or code-level constants — no PII, no user input, no credentials. This is standard and appropriate error reporting context.

2. rescue StandardError => nil in wrapper — INFORMATIONAL
The silent rescue in ErrorReporting.report is intentional and correct. Error reporting must never impact application runtime. The original error handling flow continues regardless. Well-established defensive pattern.

3. Pre-existing rescue Exception in callers — INFORMATIONAL (pre-existing)
latest_version.rb and ping_home_base.rb rescue Exception (not StandardError), which catches SignalException, SystemExit, etc. This is pre-existing and not introduced by this PR. Consider narrowing to StandardError in a future cleanup pass, but out of scope here.

4. No validation on context hash — INFORMATIONAL
All context hashes are constructed inline with known literals at each call site. No user-supplied input flows into context. No injection or data leakage risk.


Automated security review · reviewer: security-sentinel

@kitcommerce kitcommerce added review:architecture-done Review complete review:security-done Review complete and removed review:architecture-pending Review in progress review:security-pending Review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

Rails Conventions Review

Verdict: PASS_WITH_NOTES (LOW)


Summary

This is a well-scoped, non-breaking addition. Workarea::ErrorReporting is a thin, defensive wrapper — it doesn't fight Rails, introduce fat controllers, misuse callbacks, or create unnecessary abstraction. The call sites are all existing rescue clauses where exceptions were already being swallowed; adding a reporting hook is appropriate and unintrusive.


Findings

LOW — core/lib/workarea/error_reporting.rb line 30
defined?(Rails) is always truthy in any Rails engine/application context. The guard is harmless but unnecessary and slightly unusual — a reader may wonder if there's an edge case where Rails isn't defined (there isn't, in normal operation). Prefer:

def rails_error_reporter_available?
  Rails.respond_to?(:error) && Rails.error.respond_to?(:report)
end

The intent (Rails version compatibility) is already expressed by the respond_to? checks.


LOW — core/lib/workarea/error_reporting.rb (new file, lib/ placement)
The diff doesn't show how this file is required or made available to the rest of the engine. Files under lib/ in a Rails engine are not Zeitwerk-autoloaded by default. If this module isn't explicitly required in the engine's bootstrap (e.g. core/lib/workarea.rb or core/lib/workarea/engine.rb), calls to Workarea::ErrorReporting.report will raise NameError. Worth confirming the require chain is in place even if it's in a file not included in this diff.


LOW — core/lib/workarea/error_reporting.rbclass << self vs module_function
For a pure-utility module with no instances, module_function or extend self are slightly more idiomatic in the Rails/Ruby ecosystem — they make the methods callable as module functions while also making them available as mixins if ever needed. class << self is perfectly valid but is the more OOP-style singleton approach. Not a blocking concern at this scale; just a style note.


Recommendations

  1. Drop defined?(Rails) from the availability guard — the two respond_to? checks already do the right work.
  2. Confirm the require chain for workarea/error_reporting is in place (likely already handled, just not visible in this diff).
  3. Consider module_function or extend self over class << self if the module may ever be mixed into classes in the future.

What looks good

  • The rescue StandardError; nil wrapper around Rails.error.report is the correct pattern — error reporting infrastructure must never raise into application code.
  • Calling with handled: true, severity: :warning at all three call sites is semantically correct — these are genuinely swallowed errors, not unhandled exceptions.
  • The context: hashes are well-chosen: lightweight, structured, non-sensitive, and useful for triage.
  • The documentation in docs/rails7-migration-patterns/error-reporting.md clearly explains the rationale and avoids over-specifying implementation.
  • No callbacks, no fat controllers, no N+1s, no REST violations introduced. This change fits Rails' grain cleanly.

Reviewed by rails-conventions agent · WA-RAILS7-023

@kitcommerce kitcommerce added review:rails-conventions-done Rails conventions review complete and removed review:rails-conventions-pending Rails conventions review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

Simplicity Review

Verdict: PASS

Findings

No meaningful complexity concerns. This is a well-scoped, proportional change.

  • Module is thin by design. 36 lines, one public method, one private guard. The abstraction exists to centralize the Rails version availability check — not to generalize something that doesn't need it.
  • ** extracted as a named private method.** Called once. Could technically be inlined, but the triple-condition guard (defined?(Rails) && respond_to?...) is complex enough that naming it aids readability. Not a simplicity problem.
  • All parameters pass through to Rails 1:1. No invented configuration layer — just mirroring the Rails API with a guard around it. Appropriate.
  • rescue StandardError; nil is commented with clear intent. Defensive for an error reporter wrapper — correct call.
  • severity: :error default is never exercised by current call sites (all three pass :warning). Minor observation only — the default needs to be something, and :error is a reasonable fallback for a generic error-reporting call.
  • Call sites are consistent and minimal. Each passes contextually relevant fields and nothing else.
  • Documentation is appropriately sized — explains the why and the decision, not just the what.

Recommendations

None required. The implementation is proportional to the problem.

@kitcommerce kitcommerce added review:simplicity-done Review complete and removed review:simplicity-pending Review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

✅ Wave 1 Gate — PASSED

All 4 Wave 1 reviewers returned PASS or PASS_WITH_NOTES (all findings LOW severity).

Reviewer Verdict Severity
architecture PASS
security PASS_WITH_NOTES LOW
rails-conventions PASS_WITH_NOTES LOW
simplicity PASS

Advancing to Wave 2 (rails-security, database, test-quality).

@kitcommerce kitcommerce added review:rails-security-pending Rails security review in progress review:database-pending Database review in progress review:test-quality-pending Review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

Database Review (Wave 2)

{
  "reviewer": "database",
  "verdict": "PASS",
  "severity": null,
  "summary": "No database impact. No migrations, schema changes, model changes, or new query patterns. Pure application-layer error reporting wrapper.",
  "findings": []
}

No database concerns. This PR adds a stateless error reporting module and wires it into three existing rescue blocks. No Mongoid model fields, indexes, validations, associations, or queries were added or modified.

@kitcommerce kitcommerce added review:database-done Database review complete and removed review:database-pending Database review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

Rails Security Review (Wave 2)

{
  "reviewer": "rails-security",
  "verdict": "PASS",
  "severity": null,
  "summary": "No Rails security issues found. The change is additive, introduces no new attack surface, and all context hash values are developer-controlled literals with no user input.",
  "findings": []
}

Analysis

Checked all 10 Rails security vectors (mass assignment, SQL injection, XSS, CSRF, IDOR, auth gaps, secrets, redirects, file handling, sensitive data exposure). None apply to this change.

Context hash safety: All values passed to Rails.error.report context are developer-controlled — class names (self.class.name), internal order IDs (order&.id), and string literals for service names/URLs. No user-supplied input reaches these hashes.

Error swallowing: The rescue StandardError => nil in the wrapper is defensive design — prevents error reporting infrastructure from disrupting actual error handling. Not a security concern.

Wave 1 alignment: Consistent with Wave 1 security review (PASS_WITH_NOTES/LOW). The LOW notes from Wave 1 (context hashes, rescue Exception, no validation on context) remain informational only — no escalation warranted.

@kitcommerce kitcommerce added review:rails-security-done Rails security review complete and removed review:rails-security-pending Rails security review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

Test Quality Review (Wave 2)

{
  "reviewer": "test-quality",
  "verdict": "PASS_WITH_NOTES",
  "severity": null,
  "summary": "No tests added for the new ErrorReporting module; acceptable given its fully defensive design, but the core guard logic and rescue path are worth covering for future-proofing.",
  "findings": [
    {
      "severity": "LOW",
      "file": "core/lib/workarea/error_reporting.rb",
      "line": 1,
      "issue": "Workarea::ErrorReporting has no unit tests. The rails_error_reporter_available? guard (3-condition AND), the rescue-to-nil path, and the default parameter values (handled: true, severity: :error) are exercised only implicitly via existing integration tests. A bug in the guard would silently revert error reporting to the pre-PR status quo — no crash, but also no observability.",
      "suggestion": "Add a minimal test file (e.g. test/lib/workarea/error_reporting_test.rb) covering three cases: (1) returns nil without calling Rails.error when reporter is unavailable, (2) delegates correctly when Rails.error.report is available, (3) swallows and returns nil if Rails.error.report itself raises. These are cheap to write and protect against inadvertent guard regressions."
    }
  ]
}

Elaboration

The absence of tests is not a blocker here. The module is a transparent, side-effect-only wrapper with no return value consumed by callers. Its worst-case failure mode (a bug in rails_error_reporter_available?) silently reverts to pre-PR behavior — the same silent error swallow that existed before this change. No correctness regression, no crash.

That said, three cheap unit tests would lock in the contract permanently:

  • Guard returns early when Rails.error is absent (no Rails, or error not present, or report not present)
  • Delegates to Rails.error.report with correct arguments when available
  • Rescues internal exceptions raised by Rails.error.report (the outer rescue StandardError => nil path)

Verdict: PASS_WITH_NOTES — safe to merge, LOW-priority follow-up test gap noted.

@kitcommerce kitcommerce added review:test-quality-done Review complete and removed review:test-quality-pending Review in progress labels Mar 5, 2026
@kitcommerce
Copy link
Author

✅ Wave 2 Gate — PASSED

All 3 Wave 2 reviewers returned PASS or PASS_WITH_NOTES (LOW severity only).

Reviewer Verdict Severity
rails-security PASS
database PASS
test-quality PASS_WITH_NOTES LOW

All waves complete. Labeling merge:ready.

@kitcommerce kitcommerce added the merge:ready All conditions met, eligible for merge label Mar 5, 2026
@kitcommerce
Copy link
Author

✅ All Review Waves Passed

All reviewers returned PASS or PASS_WITH_NOTES. This PR is merge-ready.

  • Wave 1 (Foundation): ✅ arch PASS, security PASS_WITH_NOTES LOW, rails-conv PASS_WITH_NOTES LOW, simplicity PASS
  • Wave 2 (Correctness): ✅ rails-security PASS, database PASS, test-quality PASS_WITH_NOTES LOW

Labeled merge:ready. Auto-merge hold window started (60 min).

@kitcommerce kitcommerce added the merge:hold In hold window before auto-merge label Mar 5, 2026
@kitcommerce kitcommerce merged commit 7f360db into next Mar 5, 2026
15 checks passed
@kitcommerce kitcommerce deleted the wa-rails7-023-error-reporting branch March 5, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gate:build-passed Build gate passed merge:hold In hold window before auto-merge merge:ready All conditions met, eligible for merge review:architecture-done Review complete review:database-done Database review complete review:rails-conventions-done Rails conventions review complete review:rails-security-done Rails security review complete review:security-done Review complete review:simplicity-done Review complete review:test-quality-done Review complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant